package com.leectrl.server;

import android.content.SharedPreferences;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.hdl.school.application.MyApplication;
import com.leectrl.adapter.DockingTCPServerHandler;
import com.leectrl.utils.Bus;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.NetworkInterface;
import java.net.UnknownHostException;
import java.nio.charset.StandardCharsets;
import java.util.Enumeration;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.CopyOnWriteArrayList;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;

public class DockingTCPServer {
    private static final int port = 8000;
    private EventLoopGroup bossGroup;
    private EventLoopGroup workerGroup;
    private SharedPreferences sharedPreferences= MyApplication.myApplication.getSharedPreferences("school_iot", 0);
    //是否有连接被初始化
    private boolean initTag=false;


    public DockingTCPServer(){
        registeMessageBus();
    }

    public void run() throws Exception{
        CopyOnWriteArrayList<ChannelHandlerContext> mChannelHandlerContextList = new CopyOnWriteArrayList<ChannelHandlerContext>();
        CopyOnWriteArrayList<String> ipList=new CopyOnWriteArrayList<String>();
        Timer timer=new Timer();
        timer.scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {
                JSONObject aliveMsg=new JSONObject();
                aliveMsg.put("type","checkAlive");
                Bus.getInstance().emit("alive",JSON.toJSONString(aliveMsg));

            }
        },0,3000);
        //NioEventLoopGroup是用来处理IO操作的多线程事件循环器
        bossGroup= new NioEventLoopGroup(1);  // 用来接收进来的连接
        workerGroup  = new NioEventLoopGroup();// 用来处理已经被接收的连接
        try{
            ServerBootstrap server =new ServerBootstrap();//是一个启动NIO服务的辅助启动类
            server.group(bossGroup,workerGroup )
                    .channel(NioServerSocketChannel.class)  // 这里告诉Channel如何接收新的连接
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel ch) throws Exception {
                            // 自定义处理类m
                            initTag=true;
                            ChannelPipeline pipeline=ch.pipeline();
                            pipeline.addLast(new DockingTCPServerHandler(mChannelHandlerContextList,ipList));
                        }
                    });
            server.option(ChannelOption.SO_BACKLOG, 1024); // 设置tcp缓冲区
            server.option(ChannelOption.SO_SNDBUF, 32 * 1024); // 设置发送缓冲大小
            server.option(ChannelOption.SO_RCVBUF, 32 * 1024); // 这是接收缓冲大小
            server.option(ChannelOption.SO_KEEPALIVE, true); // 保持连接
            ChannelFuture f = server.bind(port).sync();// 绑定端口，开始接收进来的连接
            if(f.isSuccess()){
                System.out.println("TCP服务启动 成功---------------");
            }
            // 监听服务器关闭监听
            f.channel().closeFuture().sync();
        }finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }



    }


    /**
     * 服务关闭
     */
    public synchronized void stopServer() {
        try {
            this.workerGroup.shutdownGracefully().await();
            this.bossGroup.shutdownGracefully().await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    private void sendUDPSerial(String code) {
        String broadMac=sharedPreferences.getString("c_setting_broadMac",null);
        if (broadMac == null) {
            return;
        }
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("action", "tcp_serial");
        jsonObject.put("target", broadMac);
        JSONArray codes = new JSONArray();
        JSONObject codeObj = new JSONObject();
        codeObj.put("code", code);
        codeObj.put("delay", 0);
        codes.add(codeObj);
        jsonObject.put("codes", codes);
        byte[] command = JSON.toJSONString(jsonObject).getBytes(StandardCharsets.UTF_8);
        try {
            Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();
            NetworkInterface networkInterface;
            Enumeration<InetAddress> inetAddresses;
            InetAddress inetAddress;
            while (networkInterfaces.hasMoreElements()) {
                networkInterface = networkInterfaces.nextElement();
                inetAddresses = networkInterface.getInetAddresses();
                while (inetAddresses.hasMoreElements()) {
                    inetAddress = inetAddresses.nextElement();
                    if (inetAddress != null && inetAddress instanceof Inet4Address) { // IPV4
                        InetSocketAddress inetAddr = new InetSocketAddress(inetAddress, 0);
                        //2.获取广播socket
                        DatagramSocket broadcastSocket = new DatagramSocket(inetAddr);
                        broadcastSocket.setBroadcast(true);
                        DatagramPacket packet = new DatagramPacket(command, command.length, InetAddress.getByName("255.255.255.255"), 12357);
                        //4.发送数据
                        broadcastSocket.send(packet);
                        //5.关闭socket
                        broadcastSocket.close();
                    }
                }
            }
        } catch (UnknownHostException e) {
            //Ip地址错误时候抛出的异常
            e.printStackTrace();
        } catch (IOException e) {
            //获取socket失败时候抛出的异常
            e.printStackTrace();
        }
    }

    private void registeMessageBus(){
        Bus.getInstance().on("restart_tcp", new Bus.MessageEvent() {
            @Override
            public void onEvent(String key, Object... message) {
                stopServer();
                try {
                    run();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });

        Bus.getInstance().on("tcp_serial", new Bus.MessageEvent() {
            @Override
            public void onEvent(String key, Object... message) {
                if(initTag){
                    return ;
                }
                String code = (String) message[0];
                if(code!=null&&code.length()>=10){
                    sendUDPSerial(code);
                }
            }
        });
    }
}
